package com.ms.game.bank;

import java.math.BigDecimal;

import com.ms.game.bank.container.BankBuyFeeInfo;
import com.ms.game.bank.container.BankInfoBin;
import com.ms.game.bank.db.LoadBankBookDetailsAsync;
import com.ms.game.bank.db.UpdateAcoountCashPlayerVipDCLAsync;
import com.ms.game.bank.db.checkAndChangePasswordDCLAsync;
import com.ms.game.bank.db.checkAndCreatePasswordDCLAsync;
import com.ms.game.bank.db.checkPasswordDCLAsync;
import com.ms.game.bank.db.loadBankGoldCoinDCLAsync;
import com.ms.game.bank.db.updateAccountCashDCLAsysn;
import com.ms.game.bank.db.updateAccountWeeklyCashDCLAsysn;
import com.ms.game.bank.message.BankBuyFeeRequest;
import com.ms.game.bank.message.BankBuyFeeResponse;
import com.ms.game.bank.message.BankRequest;
import com.ms.game.bank.message.BankResponse;
import com.ms.game.bank.message.CBankBookDetailsRequest;
import com.ms.game.bank.message.SBankBookDetailsResponse;
import com.ms.game.bank.message.SBankPageResponse;
import com.ms.game.common.container.GameLimitInfo;
import com.ms.game.common.container.LevelInfoBin;
import com.ms.game.lobby.GameLobbyModule;
import com.ms.game.password.db.PasswordErrorWay;
import com.ms.game.purchase.bin.PurchaseType;
import com.ms.player.Player;
import com.ms.service.error.ErrorCode;
import com.ms.service.module.account.Account;
import com.ms.service.module.zone.BasicZone;
import com.ms.service.module.zone.module.BasicZoneModule;
import com.xpec.c4.game.datamanager.BaseDataInfo;
import com.xpec.c4.game.datamanager.ResultNo;
import com.xpec.c4.game.datamanager.agent.money.ChangeCoin;
import com.xpec.c4.game.datamanager.agent.money.CoinType;
import com.xpec.c4.game.datamanager.agent.money.MoneyChangeParam;
import com.xpec.c4.game.datamanager.agent.money.MoneyChangeWay;
import com.xpec.c4.game.login.LoginModule;
import com.xpec.c4.game.time.TimeConstants;
import com.xpec.c4.game.time.TimeSys;
import com.xpec.c4.game.utility.GUID;
import com.xpec.c4.message.MessageTypes;
import com.xpec.c4.service.message.MessageAction;
import com.xpec.c4.service.module.common.PlayerCommonInfoManager;

public class BankProcessor {

	public static final int BANK_MIN_LEVEL = 1;
	
	/**
	 * 密碼最多字數
	 */
	public static final int BANK_PASSWORD_MAX_NUM = 12;
	
	/**
	 * 密碼最少字數
	 */
	public static final int BANK_PASSWORD_MIN_NUM = 6;
	
	/**
	 * 包月上限月份 
	 * (上限12個月)
	 */
	public static final long MONTHLY_FEE_MAX_MONTH = 12*30*24*60*60*1000l;
	
	/**
	 * 一個月
	 */
	public static final long ONE_MONTH = 30*24*60*60*1000l;

	/**
	 * 包週上限月份 
	 * (上限12個月)
	 */
	public static final long WEEKLY_FEE_MAX_MONTH = 48 * TimeConstants.MILLI_SECOND_PER_WEEK;

	/**
	 * 一週
	 */
	public static final long ONE_WEEK = TimeConstants.MILLI_SECOND_PER_WEEK;

	public static void OnOpenBankPage(GUID sessionID, GameLobbyModule module , boolean needUpdate){
		
		SBankPageResponse response = new SBankPageResponse(); 
		Player playerData =null;
		GUID playerID = PlayerCommonInfoManager.getInstance().getPlayerGuidBySession(sessionID);
		if(playerID != null){
			playerData = module.getZone().getPlayer(playerID);
		}
		if(playerData == null){
			//是否有玩家資料
			response.errorCode = ErrorCode.NO_PLAYER_DATA;
			MessageAction.sendMessage(sessionID, MessageTypes.S_BANK_INFO_RESPONSE, response);
			return;
		}
		
		if(needUpdate){
			loadBankGoldCoinDCLAsync async = new loadBankGoldCoinDCLAsync();
			async.playerID = playerID;
			async.sessionID = sessionID;
			async.key = playerID;
			module.addCentralAsyncCommandToDC(async, playerData);
		}else{
			response.errorCode = ErrorCode.SUCCESS;
			response.bankGold = playerData.getBankGoldCoin().toString();
			MessageAction.sendMessage(sessionID, MessageTypes.S_BANK_INFO_RESPONSE, response);
		}
	}
	
	/**
	 * 點數轉遊戲幣
	 */
	public static void OnChangePointToGoldCoin(GUID sessionID, BankRequest request, BasicZoneModule module){
		
		BankResponse response = new BankResponse(); 
		Player playerData =null;
		GUID playerID = PlayerCommonInfoManager.getInstance().getPlayerGuidBySession(sessionID);
		BasicZone zone = module.getZone();
		boolean isFirstChange = false;
		
		if(playerID != null){
			playerData = zone.getPlayer(playerID);
		}
		if(playerData == null){
			//是否有玩家資料
			response.errorCode = ErrorCode.NO_PLAYER_DATA;
			zone.changePointToGoldCallback(sessionID , response , playerID);
			return;
		}
		
		GUID accountID = PlayerCommonInfoManager.getInstance().getAccountIdByPlayerGuid(playerID);
		if(accountID == null){
			//是否有帳號資料
			response.errorCode = ErrorCode.NO_ACCOUNT_DATA;
			zone.changePointToGoldCallback(sessionID , response , playerID);
			return;
		}
		
		//確認會員轉點限制
		int limitCode = GameLimitInfo.checkLimitByClassify(GameLimitInfo.BILLING_TRANS_POINT, playerData.getVip(),playerData.getLevel(), playerData.isVerifiedMember(), playerData.isTrialAccount(), playerData.getUplineCode());
		if(limitCode != GameLimitInfo.TRUE){
			response.errorCode = GameLimitInfo.limitToErrorCode(limitCode);
			zone.changePointToGoldCallback(sessionID , response , playerID);
			return;
		}		
		
		if(request.cashPoint <= 0){
			//沒有點數
			response.errorCode = ErrorCode.NO_CASH_POINT;
			zone.changePointToGoldCallback(sessionID , response , playerID);
			return;
			
		}

		if(playerData.getVip() <= 0){
			long vipExp = LevelInfoBin.getInstance().getVipLevelUpInfoList().get(1).getNeedExp();
			if(request.cashPoint < vipExp){
				//第一次轉點不足
				response.errorCode = ErrorCode.FIRST_CHANGE_CASH_NOT_ENOUGH;
				zone.changePointToGoldCallback(sessionID , response , playerID);
				return;
			}
		}
		// 如果帳號沒有其他轉點過的角色(表示這支是首轉)
		
		if(!playerData.isHaveFirstStoreCharacter()){
			isFirstChange = true;
		}
		
		
		//點數轉遊戲幣
		UpdateAcoountCashPlayerVipDCLAsync saveData = new UpdateAcoountCashPlayerVipDCLAsync();
		saveData.cashPoint = request.cashPoint;
		saveData.sessionID = sessionID;
		saveData.playerID = playerID;
		saveData.accountID = accountID;
		saveData.userType = playerData.getUserType();
		saveData.playerName = playerData.getName();
		saveData.isFirstChange = isFirstChange;
		saveData.key = playerID;
		module.addCentralAsyncCommand(saveData, module);
	}
	
	/**
	 * @param obj
	 * @param userObject
	 * 銀行存款提款變動
	 * {@link UpdateAcoountCashPlayerVipDCLAsync#callBackExecute(Object...)}
	 */
	public void changePointToGoldCoinCallback(BaseDataInfo obj, Object... userObject){
		BankResponse response = new BankResponse(); 
		GUID sessionID = (GUID)userObject[0];
		int messageType = (int)userObject[1];
		BasicZoneModule module = (BasicZoneModule)userObject[2];
		long afterAccountCash = (long)userObject[3]; //TODO: 更新login帳號點數
		MoneyChangeParam param = (MoneyChangeParam) obj.getData();
		
		
		ChangeCoin coin = param.getChangeCoinLister().getCoinMap().get(CoinType.GOLD);
		GUID playerID = PlayerCommonInfoManager.getInstance().getPlayerGuidBySession(sessionID);
		
		BasicZone zone = module.getZone();
		
		if(obj.getResultCode() == ResultNo.OK){
			Player playerData = null;
			if(playerID != null){
				playerData = module.getZone().getPlayer(playerID);
			}
			if(playerData != null){
				//玩家在線上
				response.vip = playerData.getVip();
				response.vipExp = playerData.getVipExp();
			}
			response.errorCode = ErrorCode.SUCCESS;
			response.goldCoin = coin.getNewValue().toString();
			response.accountCashPoint = afterAccountCash;
		}else{
			response.errorCode = obj.getResultCode();
		}
		
		zone.changePointToGoldCallback(sessionID , response , playerID);
	}
	
	/**
	 * @param sessionID
	 * @param request
	 * @param module
	 * 存款
	 * {@link com.ms.game.bank.BankProcessor#bankChangeMoneyCallback}
	 */
	public static void OnDeposit(GUID sessionID, BankRequest request, GameLobbyModule module){
		BankResponse response = new BankResponse(); 

		if(module.isStopTransaction()){
			response.errorCode = ErrorCode.GAME_SERVER_WAIT_TO_CLOSE;
			MessageAction.sendMessage(sessionID, MessageTypes.S_BANK_DEPOSIT_RESPONSE, response);
			return;
		}
		
		Player playerData =null;
		GUID playerID = PlayerCommonInfoManager.getInstance().getPlayerGuidBySession(sessionID);
		if(playerID != null){
			playerData = module.getZone().getPlayer(playerID);
		}
		if(playerData == null){
			//是否有玩家資料
			response.errorCode = ErrorCode.NO_PLAYER_DATA;
			MessageAction.sendMessage(sessionID, MessageTypes.S_BANK_DEPOSIT_RESPONSE, response);
			return;
		}
		
		GUID accountID = PlayerCommonInfoManager.getInstance().getAccountIdByPlayerGuid(playerID);
		if(accountID == null){
			//是否有帳號資料
			response.errorCode = ErrorCode.NO_ACCOUNT_DATA;
			MessageAction.sendMessage(sessionID, MessageTypes.S_BANK_DEPOSIT_RESPONSE, response);
			return;
		}
		
		//確認會員限制
		int limitCode = GameLimitInfo.checkLimitByClassify(GameLimitInfo.BANK_ATM, playerData.getVip(),playerData.getLevel(), playerData.isVerifiedMember(), playerData.isTrialAccount(), playerData.getUplineCode());
		if(limitCode != GameLimitInfo.TRUE){
			response.errorCode = GameLimitInfo.limitToErrorCode(limitCode);
			MessageAction.sendMessage(sessionID, MessageTypes.S_BANK_DEPOSIT_RESPONSE, response);
			return;
		}
		
		
		if(playerData.getLevel() < BANK_MIN_LEVEL){
			//玩家等級不足
			response.errorCode = ErrorCode.PLAYER_LEVEL_NOT_ENOUGH;
			MessageAction.sendMessage(sessionID, MessageTypes.S_BANK_DEPOSIT_RESPONSE, response);
			return;
		}
		
		if(request.goldCoin <= 0){
			//不能小於等於0
			response.errorCode = ErrorCode.INVALID_PARAM;
			MessageAction.sendMessage(sessionID, MessageTypes.S_BANK_DEPOSIT_RESPONSE, response);
			return;
		}
		
		if(playerData.getDisableTime() > TimeSys.currentTimeMills()){
			//錯誤太多次時間內不能操作
			response.disableTime = playerData.getDisableTime();
			response.errorCode = ErrorCode.PASSWORD_ERROR_DISABLE_TIME;
			MessageAction.sendMessage(sessionID, MessageTypes.S_BANK_DEPOSIT_RESPONSE, response);
			return;
		}
		
		//密碼全轉大寫
		request.password = request.password.toUpperCase();
		
		//密碼判斷
		checkPasswordDCLAsync loadAndCheck = new checkPasswordDCLAsync();
		loadAndCheck.accountID = accountID;
		loadAndCheck.playerID = playerID;
		loadAndCheck.playName = playerData.getName();
		loadAndCheck.sessionID = sessionID;
		loadAndCheck.password = request.password;
		loadAndCheck.errorWay = PasswordErrorWay.ERROR_BANK_DEPOSIT;
		module.addCentralAsyncCommand(loadAndCheck, module, playerData, 
				MoneyChangeWay.SUB_BANK_DEPOSIT, request.goldCoin, MessageTypes.S_BANK_DEPOSIT_RESPONSE);

	}
	
	/**
	 * @param sessionID
	 * @param request
	 * @param module
	 * 提款
	 * {@link com.ms.game.bank.BankProcessor#bankChangeMoneyCallback}
	 */
	public static void OnGetCash(GUID sessionID, BankRequest request, GameLobbyModule module){
		BankResponse response = new BankResponse(); 
		if(module.isStopTransaction()){
			response.errorCode = ErrorCode.GAME_SERVER_WAIT_TO_CLOSE;
			MessageAction.sendMessage(sessionID, MessageTypes.S_BANK_GET_CASH_RESPONSE, response);
			return;
		}
		
		Player playerData =null;
		GUID playerID = PlayerCommonInfoManager.getInstance().getPlayerGuidBySession(sessionID);
		if(playerID != null){
			playerData = module.getZone().getPlayer(playerID);
		}
		if(playerData == null){
			//是否有玩家資料
			response.errorCode = ErrorCode.NO_PLAYER_DATA;
			MessageAction.sendMessage(sessionID, MessageTypes.S_BANK_GET_CASH_RESPONSE, response);
			return;
		}
		
		GUID accountID = PlayerCommonInfoManager.getInstance().getAccountIdByPlayerGuid(playerID);
		if(accountID == null){
			//是否有帳號資料
			response.errorCode = ErrorCode.NO_ACCOUNT_DATA;
			MessageAction.sendMessage(sessionID, MessageTypes.S_BANK_GET_CASH_RESPONSE, response);
			return;
		}
		
		//確認會員限制  
		int limitCode = GameLimitInfo.checkLimitByClassify(GameLimitInfo.BANK_ATM, playerData.getVip(),playerData.getLevel(), playerData.isVerifiedMember(), playerData.isTrialAccount(), playerData.getUplineCode());
		if(limitCode != GameLimitInfo.TRUE){
			response.errorCode = GameLimitInfo.limitToErrorCode(limitCode);
			MessageAction.sendMessage(sessionID, MessageTypes.S_BANK_GET_CASH_RESPONSE, response);
			return;
		}		
		
		if(playerData.getLevel() < BANK_MIN_LEVEL){
			//玩家等級不足
			response.errorCode = ErrorCode.PLAYER_LEVEL_NOT_ENOUGH;
			MessageAction.sendMessage(sessionID, MessageTypes.S_BANK_GET_CASH_RESPONSE, response);
			return;
		}
		
		if(playerData.getDisableTime() > TimeSys.currentTimeMills()){
			//錯誤太多次時間內不能操作
			response.disableTime = playerData.getDisableTime();
			response.errorCode = ErrorCode.PASSWORD_ERROR_DISABLE_TIME;
			MessageAction.sendMessage(sessionID, MessageTypes.S_BANK_GET_CASH_RESPONSE, response);
			return;
		}
		
		if(request.goldCoin <= 0){
			//不能小於等於0
			response.errorCode = ErrorCode.INVALID_PARAM;
			MessageAction.sendMessage(sessionID, MessageTypes.S_BANK_GET_CASH_RESPONSE, response);
			return;
		}
		
		//密碼全轉大寫
		request.password = request.password.toUpperCase();
		
		//密碼判斷
		checkPasswordDCLAsync loadAndCheck = new checkPasswordDCLAsync();
		loadAndCheck.accountID = accountID;
		loadAndCheck.playerID = playerID;
		loadAndCheck.playName = playerData.getName();
		loadAndCheck.sessionID = sessionID;
		loadAndCheck.password = request.password;
		loadAndCheck.errorWay = PasswordErrorWay.ERROR_BANK_GET_MONEY;
		loadAndCheck.key = playerID;
		module.addCentralAsyncCommand(loadAndCheck, module, playerData, 
				MoneyChangeWay.ADD_BANK_GET_CASH, request.goldCoin, MessageTypes.S_BANK_GET_CASH_RESPONSE);
				
	}
	
	/**
	 * @param obj
	 * @param userObject
	 * 銀行存款提款變動
	 * {@link com.ms.game.bank.BankProcessor#OnDeposit}
	 * {@link com.ms.game.bank.BankProcessor#OnGetCash}
	 */
	public void bankChangeMoneyCallback(BaseDataInfo obj, Object... userObject){
		BankResponse response = new BankResponse(); 
		GUID sessionID = (GUID)userObject[0];
		int messageType = (int)userObject[1];
		GameLobbyModule module = (GameLobbyModule)userObject[2];
		MoneyChangeParam param = (MoneyChangeParam) obj.getData();
		
		BigDecimal changeGold = param.getChangeCoinLister().getCoinMap().get(CoinType.GOLD).getChangeValue();
		
		if(obj.getResultCode() == ResultNo.OK){
			GUID playerID = PlayerCommonInfoManager.getInstance().getPlayerGuidBySession(sessionID);
			Player playerData = null;
			if(playerID != null){
				playerData = module.getZone().getPlayer(playerID);
			}
			if(playerData != null){
				response.bankGold = playerData.getBankGoldCoin().toString();
				response.goldCoin = param.getChangeCoinLister().getCoinMap().get(CoinType.GOLD).getNewValue().toString();
			}
			
			response.errorCode = ErrorCode.SUCCESS;
			MessageAction.sendMessage(sessionID, messageType, response);
		}else{
			response.errorCode = obj.getResultCode();
			MessageAction.sendMessage(sessionID, messageType, response);	
		}
		
	}
	
	/**
	 * 在大廳內創建密碼
	 */
	public static void OnCreatePasswordInLobby(GUID sessionID, BankRequest request, GameLobbyModule module){
		BankResponse response = new BankResponse();
		
		if(module.isStopTransaction()){
			response.errorCode = ErrorCode.GAME_SERVER_WAIT_TO_CLOSE;
			MessageAction.sendMessage(sessionID, MessageTypes.S_BANK_CREATE_PASSWORD_INLOBBY_RESPONSE, response);
			return;
		}
		
		Player playerData =null;
		GUID playerID = PlayerCommonInfoManager.getInstance().getPlayerGuidBySession(sessionID);
		if(playerID != null){
			playerData = module.getZone().getPlayer(playerID);
		}
		if(playerData == null){
			//是否有玩家資料
			response.errorCode = ErrorCode.NO_PLAYER_DATA;
			MessageAction.sendMessage(sessionID, MessageTypes.S_BANK_CREATE_PASSWORD_INLOBBY_RESPONSE, response);
			return;
		}
		
		GUID accountID = PlayerCommonInfoManager.getInstance().getAccountIdByPlayerGuid(playerID);
		if(accountID == null){
			//是否有帳號資料
			response.errorCode = ErrorCode.NO_ACCOUNT_DATA;
			MessageAction.sendMessage(sessionID, MessageTypes.S_BANK_CREATE_PASSWORD_INLOBBY_RESPONSE, response);
			return;
		}
		
		if(playerData.getLevel() < BANK_MIN_LEVEL){
			//玩家等級不足
			response.errorCode = ErrorCode.PLAYER_LEVEL_NOT_ENOUGH;
			MessageAction.sendMessage(sessionID, MessageTypes.S_BANK_CREATE_PASSWORD_INLOBBY_RESPONSE, response);
			return;
		}
		//密碼全轉大寫
		request.password = request.password.toUpperCase();
		request.rePassword = request.rePassword.toUpperCase();
		request.prePassword = request.prePassword.toUpperCase();
		if(request.password == null){
			//參數不正確
			response.errorCode = ErrorCode.INVALID_PARAM;
			MessageAction.sendMessage(sessionID, MessageTypes.S_BANK_CREATE_PASSWORD_INLOBBY_RESPONSE, response);
			return;
		}
		
		if(request.password.length() < BANK_PASSWORD_MIN_NUM || request.password.length() > BANK_PASSWORD_MAX_NUM){
			//密碼字數不合
			response.errorCode = ErrorCode.PASSWORD_NUM_NOT_ENOUGH;
			MessageAction.sendMessage(sessionID, MessageTypes.S_BANK_CREATE_PASSWORD_INLOBBY_RESPONSE, response);
			return;
		}
		
		if(!request.password.equals(request.rePassword)){
			//重複輸入密碼不同
			response.errorCode = ErrorCode.REPASSWORD_NOT_SAME;
			MessageAction.sendMessage(sessionID, MessageTypes.S_BANK_CREATE_PASSWORD_INLOBBY_RESPONSE, response);
			return;
		}
		
		//密碼中一定要包含數字英文
		//"^.*(?=.[0-9])(.*[A-Z])|(?=.[A-Z])(.*[0-9])+.*$"
		if(!passwordMatches(request.password)) //任何後面有 (數字英文)或(英文數字)的
		{
			//密碼中必須要有英文和數字
			response.errorCode = ErrorCode.PASSWORD_NEED_EN_AND_NUMBER;
			MessageAction.sendMessage(sessionID, MessageTypes.S_BANK_CREATE_PASSWORD_INLOBBY_RESPONSE, response);
			return;
		}
		
		checkAndCreatePasswordDCLAsync saveData = new checkAndCreatePasswordDCLAsync();
		saveData.accountID = accountID;
		saveData.sessionID = sessionID;
		saveData.password = request.password;
		saveData.isFormLogin = false;
		saveData.messageType = MessageTypes.S_BANK_CREATE_PASSWORD_INLOBBY_RESPONSE;
		saveData.setRobot(playerData.isRobot());
		module.addCentralAsyncCommand(saveData);
		
	}
	
	/**
	 * 密碼更改
	 */
	public static void OnCreatePassword(GUID sessionID, BankRequest request, GUID accountID, Account account, LoginModule module){
		BankResponse response = new BankResponse(); 
		
		if(module.isStopTransaction()){
			response.errorCode = ErrorCode.GAME_SERVER_WAIT_TO_CLOSE;
			MessageAction.sendMessage(sessionID, MessageTypes.S_BANK_CREATE_PASSWORD_RESPONSE, response);
			return;
		}
		
		if(account == null){
			//是否有帳號資料
			response.errorCode = ErrorCode.NO_ACCOUNT_DATA;
			MessageAction.sendMessage(sessionID, MessageTypes.S_BANK_CREATE_PASSWORD_RESPONSE, response);
			return;
		}
		//密碼全轉大寫
		request.password = request.password.toUpperCase();
		request.rePassword = request.rePassword.toUpperCase();
		request.prePassword = request.prePassword.toUpperCase();
		if(request.password == null){
			//參數不正確
			response.errorCode = ErrorCode.INVALID_PARAM;
			MessageAction.sendMessage(sessionID, MessageTypes.S_BANK_CREATE_PASSWORD_RESPONSE, response);
			return;
		}
		
		if(request.password.length() < BANK_PASSWORD_MIN_NUM || request.password.length() > BANK_PASSWORD_MAX_NUM){
			//密碼字數不合
			response.errorCode = ErrorCode.PASSWORD_NUM_NOT_ENOUGH;
			MessageAction.sendMessage(sessionID, MessageTypes.S_BANK_CREATE_PASSWORD_RESPONSE, response);
			return;
		}
		
		if(!request.password.equals(request.rePassword)){
			//重複輸入密碼不同
			response.errorCode = ErrorCode.REPASSWORD_NOT_SAME;
			MessageAction.sendMessage(sessionID, MessageTypes.S_BANK_CREATE_PASSWORD_RESPONSE, response);
			return;
		}
		
		//密碼中一定要包含數字英文
		//"^.*(?=.[0-9])(.*[A-Z])|(?=.[A-Z])(.*[0-9])+.*$"
		if(!passwordMatches(request.password)) //任何後面有 (數字英文)或(英文數字)的
		{
			//密碼中必須要有英文和數字
			response.errorCode = ErrorCode.PASSWORD_NEED_EN_AND_NUMBER;
			MessageAction.sendMessage(sessionID, MessageTypes.S_BANK_CREATE_PASSWORD_RESPONSE, response);
			return;
		}
		
		checkAndCreatePasswordDCLAsync saveData = new checkAndCreatePasswordDCLAsync();
		saveData.accountID = accountID;
		saveData.sessionID = sessionID;
		saveData.password = request.password;
		saveData.isFormLogin = true;
		saveData.messageType = MessageTypes.S_BANK_CREATE_PASSWORD_RESPONSE;
		saveData.setRobot(account.isRobot());
		module.addCentralAsyncCommand(saveData);
		
	}
	
	/**
	 * 密碼更改
	 */
	public static void OnChangePasswordInLobby(GUID sessionID, BankRequest request, GameLobbyModule module){
		BankResponse response = new BankResponse();
		
		if(module.isStopTransaction()){
			response.errorCode = ErrorCode.GAME_SERVER_WAIT_TO_CLOSE;
			MessageAction.sendMessage(sessionID, MessageTypes.S_BANK_CHANGE_PASSWORD_INLOBBY_RESPONSE, response);
			return;
		}
		
		Player playerData =null;
		GUID playerID = PlayerCommonInfoManager.getInstance().getPlayerGuidBySession(sessionID);
		if(playerID != null){
			playerData = module.getZone().getPlayer(playerID);
		}
		if(playerData == null){
			//是否有玩家資料
			response.errorCode = ErrorCode.NO_PLAYER_DATA;
			MessageAction.sendMessage(sessionID, MessageTypes.S_BANK_CHANGE_PASSWORD_INLOBBY_RESPONSE, response);
			return;
		}
		
		GUID accountID = PlayerCommonInfoManager.getInstance().getAccountIdByPlayerGuid(playerID);
		if(accountID == null){
			//是否有帳號資料
			response.errorCode = ErrorCode.NO_ACCOUNT_DATA;
			MessageAction.sendMessage(sessionID, MessageTypes.S_BANK_CHANGE_PASSWORD_INLOBBY_RESPONSE, response);
			return;
		}
		//密碼全轉大寫
		request.password = request.password.toUpperCase();
		request.rePassword = request.rePassword.toUpperCase();
		request.prePassword = request.prePassword.toUpperCase();
		if(request.password == null){
			//參數不正確
			response.errorCode = ErrorCode.INVALID_PARAM;
			MessageAction.sendMessage(sessionID, MessageTypes.S_BANK_CHANGE_PASSWORD_INLOBBY_RESPONSE, response);
			return;
		}
		
		if(request.password.length() < BANK_PASSWORD_MIN_NUM || request.password.length() > BANK_PASSWORD_MAX_NUM){
			//密碼字數不合
			response.errorCode = ErrorCode.PASSWORD_NUM_NOT_ENOUGH;
			MessageAction.sendMessage(sessionID, MessageTypes.S_BANK_CHANGE_PASSWORD_INLOBBY_RESPONSE, response);
			return;
		}
		
		if(!request.password.equals(request.rePassword)){
			//重複輸入密碼不同
			response.errorCode = ErrorCode.REPASSWORD_NOT_SAME;
			MessageAction.sendMessage(sessionID, MessageTypes.S_BANK_CHANGE_PASSWORD_INLOBBY_RESPONSE, response);
			return;
		}
		
		//密碼中一定要包含數字英文
		//"^.*(?=.[0-9])(.*[A-Z])|(?=.[A-Z])(.*[0-9])+.*$"
		if(!passwordMatches(request.password)) //任何後面有 (數字英文)或(英文數字)的
		{
			//密碼中必須要有英文和數字
			response.errorCode = ErrorCode.PASSWORD_NEED_EN_AND_NUMBER;
			MessageAction.sendMessage(sessionID, MessageTypes.S_BANK_CHANGE_PASSWORD_INLOBBY_RESPONSE, response);
			return;
		}
		
		if(playerData.getDisableTime() > TimeSys.currentTimeMills()){
			//錯誤太多次時間內不能操作
			response.disableTime = playerData.getDisableTime();
			response.errorCode = ErrorCode.PASSWORD_ERROR_DISABLE_TIME;
			MessageAction.sendMessage(sessionID, MessageTypes.S_BANK_CHANGE_PASSWORD_INLOBBY_RESPONSE, response);
			return;
		}
		
		checkAndChangePasswordDCLAsync saveData = new checkAndChangePasswordDCLAsync();
		saveData.accountID = accountID;
		saveData.playerID = playerID;
		saveData.playName = PlayerCommonInfoManager.getInstance().getPlayerNameByGuid(playerID);
		saveData.errorWay = PasswordErrorWay.ERROR_BANK_CHANGE_PASSWORD;
		saveData.password = request.password;
		saveData.prePassword = request.prePassword;
		saveData.setRobot(playerData.isRobot());
		module.addCentralAsyncCommand(saveData, module, 
				MessageTypes.S_BANK_CHANGE_PASSWORD_INLOBBY_RESPONSE, sessionID);

	}
	
	/**
	 * 使用點數包月(Action在basiczone)
	 */
	public static void OnBuyMonthlyFeeByPoint(GUID sessionID, BasicZoneModule module){
		
		BankResponse response = new BankResponse(); 
		
		if(module.isStopTransaction()){						
			response.errorCode = ErrorCode.GAME_SERVER_WAIT_TO_CLOSE;					
			MessageAction.sendMessage(sessionID, MessageTypes.S_BANK_MONTHLY_FEE_RESPONSE, response);					
			return;					
		}						
		
		Player playerData =null;
		boolean isFirstChange = false;
		GUID playerID = PlayerCommonInfoManager.getInstance().getPlayerGuidBySession(sessionID);
		if(playerID != null){
			playerData = module.getZone().getPlayer(playerID);
		}
		if(playerData == null){
			//是否有玩家資料
			response.errorCode = ErrorCode.NO_PLAYER_DATA;
			MessageAction.sendMessage(sessionID, MessageTypes.S_BANK_MONTHLY_FEE_RESPONSE, response);
			return;
		}
		
		GUID accountID = PlayerCommonInfoManager.getInstance().getAccountIdByPlayerGuid(playerID);
		if(accountID == null){
			//是否有帳號資料
			response.errorCode = ErrorCode.NO_ACCOUNT_DATA;
			MessageAction.sendMessage(sessionID, MessageTypes.S_BANK_MONTHLY_FEE_RESPONSE, response);
			return;
		}
		
		//包月月費
		long cashPoint = BankInfoBin.getInstance().getMonthlyFee();
		
		if(playerData.getMonthlyFeeEndTime() + ONE_MONTH > TimeSys.currentTimeMills() + MONTHLY_FEE_MAX_MONTH){
			//不得超過12個月
			response.errorCode = ErrorCode.MONTHLY_FEE_TOTAL_DAY_OVERFLOW;
			MessageAction.sendMessage(sessionID, MessageTypes.S_BANK_MONTHLY_FEE_RESPONSE, response);
			return;
		}
		
		if(!playerData.isHaveFirstStoreCharacter()){
			isFirstChange = true;
		}
		
		updateAccountCashDCLAsysn loadData = new updateAccountCashDCLAsysn();
		loadData.sessionID = sessionID;
		loadData.playerID = playerID;
		loadData.playerName = playerData.getNameWithNumber();
		loadData.robot = playerData.isRobot();
		loadData.accountID = accountID;
		loadData.cashPoint = cashPoint;
		loadData.isFirstChange = isFirstChange; 
		loadData.key = playerID;
		loadData.userType = playerData.getUserType();
 		module.addCentralAsyncCommandToDC(loadData, module, playerData);
		
	}
	
	/**
	 * 使用點數包月/週(Action在basiczone)
	 */
	public static void OnBuyWeeklyFeeByPoint(GUID sessionID, BasicZoneModule module, BankBuyFeeRequest request){
		
		BankBuyFeeResponse response = new BankBuyFeeResponse(); 
		
		if(module.isStopTransaction()){						
			response.errorCode = ErrorCode.GAME_SERVER_WAIT_TO_CLOSE;					
			MessageAction.sendMessage(sessionID, MessageTypes.S_BANK_BUY_FEE_RESPONSE, response);					
			return;					
		}						
		
		Player playerData =null;
		boolean isFirstChange = false;
		GUID playerID = PlayerCommonInfoManager.getInstance().getPlayerGuidBySession(sessionID);
		if(playerID != null){
			playerData = module.getZone().getPlayer(playerID);
		}
		if(playerData == null){
			//是否有玩家資料
			response.errorCode = ErrorCode.NO_PLAYER_DATA;
			MessageAction.sendMessage(sessionID, MessageTypes.S_BANK_BUY_FEE_RESPONSE, response);
			return;
		}
		
		GUID accountID = PlayerCommonInfoManager.getInstance().getAccountIdByPlayerGuid(playerID);
		if(accountID == null){
			//是否有帳號資料
			response.errorCode = ErrorCode.NO_ACCOUNT_DATA;
			MessageAction.sendMessage(sessionID, MessageTypes.S_BANK_BUY_FEE_RESPONSE, response);
			return;
		}
		
		//包月/週費用
		int type = request.type;
//		if (!(type == PurchaseType.MONTH || type == PurchaseType.WEEK)) { // 找不到包的類型
		if(type != PurchaseType.WEEK) {
			response.errorCode = ErrorCode.DATA_NOT_FOUND;
			MessageAction.sendMessage(sessionID,
					MessageTypes.S_BANK_BUY_FEE_RESPONSE, response);
			return;
		}
		
		long cashPoint = ((BankBuyFeeInfo) BankInfoBin.getInstance().getFeeInfos().get(type)).getFee();
		
		if(type == PurchaseType.MONTH && (playerData.getMonthlyFeeEndTime() + ONE_MONTH) > (TimeSys.currentTimeMills() + MONTHLY_FEE_MAX_MONTH)){
			//不得超過12個月
			response.errorCode = ErrorCode.WEEKLY_TOTAL_OVERFLOW;
			MessageAction.sendMessage(sessionID, MessageTypes.S_BANK_BUY_FEE_RESPONSE, response);
			return;
		} else if (type == PurchaseType.WEEK && (playerData.getWeeklyFeeEndTime() + ONE_WEEK) > (TimeSys.currentTimeMills() + WEEKLY_FEE_MAX_MONTH)) {
			//不得超過48週(7*4)
			response.errorCode = ErrorCode.WEEKLY_TOTAL_OVERFLOW;
			MessageAction.sendMessage(sessionID, MessageTypes.S_BANK_BUY_FEE_RESPONSE, response);
			return;
		} 
		
		if(!playerData.isHaveFirstStoreCharacter()){
			isFirstChange = true;
		}
		
		updateAccountWeeklyCashDCLAsysn loadData = new updateAccountWeeklyCashDCLAsysn();
		loadData.sessionID = sessionID;
		loadData.playerID = playerID;
		loadData.playerName = playerData.getNameWithNumber();
		loadData.robot = playerData.isRobot();
		loadData.accountID = accountID;
		loadData.cashPoint = cashPoint;
		loadData.isFirstChange = isFirstChange; 
		loadData.key = playerID;
		loadData.buyFeeType = type;
		loadData.userType = playerData.getUserType();
 		module.addCentralAsyncCommandToDC(loadData, module, playerData);
		
	}

	
	
	
	
	
	
//	//
//	public static void OnGetRebateCoinsByType(GUID sessionID, GameLobbyModule module){
//		BankMoneyChangeWay changeWay = BankMoneyChangeWay.ADD_MONTHLY_FEE_DAILY_PAY;
//		
//		BankResponse response = new BankResponse(); 
//		Player playerData =null;
//		GUID playerID = PlayerCommonInfoManager.getInstance().getPlayerGuidBySession(sessionID);
//		if(playerID != null){
//			playerData = module.getZone().getPlayer(playerID);
//		}
//		if(playerData == null){
//			//是否有玩家資料
//			response.errorCode = ErrorCode.NO_PLAYER_DATA;
//			MessageAction.sendMessage(sessionID, MessageTypes.S_BANK_MONTHLY_DAILY_AWARD_RESPONSE, response);
//			return;
//		}
//		
//		GUID accountID = PlayerCommonInfoManager.getInstance().getAccountIdByPlayerGuid(playerID);
//		if(accountID == null){
//			//是否有帳號資料
//			response.errorCode = ErrorCode.NO_ACCOUNT_DATA;
//			MessageAction.sendMessage(sessionID, MessageTypes.S_BANK_MONTHLY_DAILY_AWARD_RESPONSE, response);
//			return;
//		}
//		
//		
//		
//		
//	 	GetSingleRebateCoinDCLAsync saveData = new GetSingleRebateCoinDCLAsync();
//	 	saveData.playerID = playerData.getGuid();
//	 	saveData.playerName = playerData.getName();
//	 	saveData.accountID = accountID;
//	 	saveData.sessionID = sessionID;
//	 	saveData.nowTime = new Date().getTime();
//	 	saveData.changeWay = changeWay;
//	 	module.addCentralAsyncCommand(saveData, module);
//	}

	
	/**
	 * 至少一個英文和數字
	 */
	private static boolean passwordMatches(String str){
		
		if(str.matches("([A-Z])*")){
			return false;
		}
		
		if(str.matches("([0-9])*")){
			return false;
		}
		
		if(str.matches("([A-Z]|[0-9])*")){
				return true;
		}
		
		return false;
	}
	
	public static void OnGetBankBookDetails(GUID sessionID, GameLobbyModule module, CBankBookDetailsRequest request) {
		SBankBookDetailsResponse response = new SBankBookDetailsResponse();
		int messageTye = MessageTypes.S_BANK_GET_BANKBOOK_DETAILS_RESPONSE;
		GUID playerID = PlayerCommonInfoManager.getInstance().getPlayerGuidBySession(sessionID);
		Player playerData = null;
		if (playerID != null) {
			playerData = module.getZone().getPlayer(playerID);
		}
		if (playerData == null) {
			response.setErrorCode(ErrorCode.NO_PLAYER_DATA);
			MessageAction.sendMessage(sessionID, messageTye, response);
			return;
		}
		GUID accountId = PlayerCommonInfoManager.getInstance().getAccountIdByPlayerGuid(playerID);
		if(accountId == null){
			response.setErrorCode(ErrorCode.NO_ACCOUNT_DATA);
			MessageAction.sendMessage(sessionID, messageTye, response);
			return;
		}
		
		LoadBankBookDetailsAsync async = new LoadBankBookDetailsAsync();
		async.playerID = playerID;
		async.key = playerID;
		async.startTime = request.getStartTime();
		async.endTime = request.getEndTime();
		async.sessionID = sessionID;
		async.accountID = accountId;
		async.osType = playerData.getOsType();
		async.messageType = messageTye;
		module.addAsyncCommand(async);
	}

}
